using System;
using System.Buffers;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualBasic;
using UMC.Data;

namespace UMC.Net
{
    public class StringValue
    {


        public static readonly StringValue Https = new StringValue("https");
        public static readonly StringValue Http = new StringValue("http");
        public static readonly StringValue IfNoneMatch = new StringValue("If-None-Match");
        public static readonly StringValue XForwardedHost = new StringValue("X-Forwarded-Host".UTF8());
        public static readonly StringValue XForwardedFor = new StringValue("X-Forwarded-For".UTF8());
        public static readonly StringValue XForwardedProxy = new StringValue("X-Forwarded-Proxy".UTF8());
        public static readonly StringValue XForwardedProto = new StringValue("X-Forwarded-Proto".UTF8());
        public static readonly StringValue XRealIP = new StringValue("X-Real-Ip".UTF8());
        public static readonly StringValue AccessControlAllowOrigin = new StringValue("Access-Control-Allow-Origin".UTF8());
        public static readonly StringValue AccessControlAllowHeaders = new StringValue("Access-Control-Allow-Headers".UTF8());

        public static readonly StringValue AccessControlAllowCredentials = new StringValue("Access-Control-Allow-Credentials".UTF8());
        public static readonly StringValue ContentRange = new StringValue("Content-Range".UTF8());
        public static readonly StringValue Host = new StringValue("Host".UTF8());
        public static readonly StringValue AcceptRanges = new StringValue("Accept-Ranges".UTF8());
        public static readonly StringValue ContentLength = new StringValue("Content-Length".UTF8());
        public static readonly StringValue ContentType = new StringValue("Content-Type".UTF8());
        public static readonly StringValue ContentDisposition = new StringValue("Content-Disposition".UTF8());
        public static readonly StringValue Location = new StringValue("Location".UTF8());
        public static readonly StringValue Connection = new StringValue("Connection".UTF8());
        public static readonly StringValue KeepAlive = new StringValue("Keep-Alive".UTF8());
        public static readonly StringValue TransferEncoding = new StringValue("Transfer-Encoding".UTF8());
        public static readonly StringValue Upgrade = new StringValue("Upgrade".UTF8());

        public static readonly StringValue SecFetchDest = new StringValue("Sec-Fetch-Dest".UTF8());
        public static readonly StringValue SecFetchMode = new StringValue("Sec-Fetch-Mode".UTF8());
        public static readonly StringValue SecFetchSite = new StringValue("Sec-Fetch-Site".UTF8());
        public static readonly StringValue SecCaUa = new StringValue("Sec-Ca-Ua".UTF8());
        public static readonly StringValue SecCaUaMobile = new StringValue("Sec-Ca-Ua-Mobile".UTF8());
        public static readonly StringValue SecCaUaPlatform = new StringValue("Sec-Ca-Ua-Platform".UTF8());

        public static readonly StringValue Cookie = new StringValue("Cookie".UTF8());
        public static readonly StringValue ContentEncoding = new StringValue("Content-Encoding".UTF8());
        public static readonly StringValue SetCookie = new StringValue("Set-Cookie".UTF8());//image/x-icon
        public static readonly StringValue ContentTypeImageIcon = new StringValue("image/x-icon".UTF8());
        public static readonly StringValue ContentTypeImageSvg = new StringValue("image/svg+xml".UTF8());
        public static readonly StringValue ContentTypeImageAvif = new StringValue("image/avif".UTF8());
        public static readonly StringValue ContentTypeImagePng = new StringValue("image/png".UTF8());
        public static readonly StringValue ContentTypeImageWebP = new StringValue("image/webp".UTF8());
        public static readonly StringValue ContentTypeJson = new StringValue("application/json; charset=utf-8".UTF8());
        public static readonly StringValue ContentTypeStream = new StringValue("application/octet-stream".UTF8());

        public static readonly StringValue ContentTypeJS = new StringValue("text/javascript; charset=utf-8".UTF8());
        public static readonly StringValue ContentTypeHtml = new StringValue("text/html; charset=utf-8".UTF8());
        public static readonly StringValue ContentTypeCss = new StringValue("text/css; charset=utf-8".UTF8());
        public static readonly StringValue ContentTypeText = new StringValue("text/plain; charset=utf-8".UTF8());
        public static readonly StringValue CacheControl = new StringValue("Cache-Control".UTF8());
        public static readonly StringValue Pragma = new StringValue("Pragma".UTF8());
        //
        public static readonly StringValue AcceptEncoding = new StringValue("Accept-Encoding".UTF8());
        public static readonly StringValue AcceptLanguage = new StringValue("Accept-Language".UTF8());
        public static readonly StringValue Origin = new StringValue("Origin");
        public static readonly StringValue Referer = new StringValue("Referer");
        public static readonly StringValue ETag = new StringValue("ETag".UTF8());
        // public static readonly StringValue XCacheKey = new StringValue("X-Cache-Key".UTF8());
        public static readonly StringValue UserAgent = new StringValue("User-Agent".UTF8());
        public static readonly StringValue LastModified = new StringValue("Last-Modified".UTF8());
        public static readonly StringValue ContentTypeUrlencode = new StringValue("application/x-www-form-urlencoded".UTF8());

        public static StringValue Empty = new StringValue(Array.Empty<byte>());
        private readonly StringSegment mValue;
        public StringValue(byte[] array, int start, int length)
        {

            mValue = StringSegment.Segment(array, start, length);
        }

        public StringValue(byte[] value)
        {
            this.mValue = StringSegment.Segment(value, 0, value.Length);
        }
        public StringValue(String value)
        {
            if (String.IsNullOrEmpty(value))
            {
                this.mValue = StringSegment.Empty;
            }
            else
            {
                var v = value.UTF8();
                this.mValue = StringSegment.Segment(v, 0, v.Length);
            }
        }
        public StringValue(StringSegment value)
        {
            this.mValue = value;
        }
        public bool IsEmpty => this.mValue.IsEmpty;
        public Span<byte> Span
        {
            get
            {
                return mValue.Value;

            }
        }
        public int Length
        {
            get
            {
                return this.mValue.Length;// _length;// mValue.IsEmpty ? sValue.Length : mValue.Length;// new StringValue(mValue.Slice(start));
            }

        }
        public override int GetHashCode()
        {
            var code = new HashCode();
            code.AddBytes(this.Span);
            return code.ToHashCode();// new HashCode.Combine(this.Span);// base.GetHashCode();
        }
        public StringValue Slice(int start)
        {
            return new StringValue(this.mValue.Slice(start, this.mValue.Length - start));
        }
        public StringValue Slice(ReadOnlySpan<byte> bytes)
        {
            var i = this.Span.IndexOf(bytes);
            if (i > -1)
            {
                return this.Slice(0, i);
            }
            return this;
        }
        public StringValue[] Split(ReadOnlySpan<byte> bytes)
        {
            var ls = new List<StringValue>();//[]
            var span = this.Span;
            int start = 0;
            int index;
            while ((index = span.IndexOf(bytes, false, start)) > -1)
            {
                if (index - start > 0)
                    ls.Add(this.Slice(start, index - start));
                start = index + 1;

            }

            if (start < span.Length)
            {
                ls.Add(this.Slice(start));
            }
            return ls.ToArray();
        }
        public StringValue[] Split(byte split)
        {
            var ls = new List<StringValue>();//[]
            var span = this.Span;
            int start = 0;
            int index;
            while ((index = span.IndexOf(split, start)) > -1)
            {
                if (index - start > 0)
                    ls.Add(this.Slice(start, index - start));
                start = index + 1;

            }
            if (start < span.Length)
            {
                ls.Add(this.Slice(start));
            }
            return ls.ToArray();
        }
        public StringValue Slice(int start, int length)
        {
            if (start < this.mValue.Length && length > 0)
                return new StringValue(this.mValue.Slice(start, length));
            return Empty;
        }
        public ReadOnlyMemory<byte> Memory
        {
            get
            {
                return this.mValue.Memory;
            }
        }
        public override string ToString()
        {
            return this.Span.UTF8();
        }
        public void Output(NetWriteData writeData)
        {
            this.mValue.Output(writeData);
        }

    }
}